package me.lc.hammerheads.sprite;

import java.util.Timer;
import java.util.TimerTask;

import me.lc.hammerheads.core.GameManager;
import me.lc.hammerheads.core.GameSystem;
import me.lc.hammerheads.util.AudioHelper;

import com.wiyun.engine.actions.Action;
import com.wiyun.engine.actions.Action.Callback;
import com.wiyun.engine.actions.Blink;
import com.wiyun.engine.actions.FadeTo;
import com.wiyun.engine.actions.IntervalAction;
import com.wiyun.engine.actions.MoveTo;
import com.wiyun.engine.actions.ProgressTo;
import com.wiyun.engine.nodes.Director;
import com.wiyun.engine.nodes.Label;
import com.wiyun.engine.nodes.Node;
import com.wiyun.engine.nodes.ProgressTimer;
import com.wiyun.engine.nodes.Sprite;
import com.wiyun.engine.opengl.Texture2D;
import com.wiyun.engine.types.WYColor3B;
import com.wiyun.engine.types.WYPoint;
import com.wiyun.engine.types.WYRect;
import com.wiyun.engine.utils.ResolutionIndependent;

/**
 * Dwarf基类
 * 
 * @author Administrator
 * 
 */
public abstract class Dwarf extends Node {

	protected Sprite dwarf;
	protected Sprite platform;
	protected ProgressTimer showTimer;
	protected ProgressTimer hideTimer;
	protected BloodInDwarf blood;
	protected Label score;
	// 是否还生存
	protected boolean isAlived;
	// 是否在hide过程中
	protected boolean isHidingProgress = false;

	protected Timer liveTimer;

	protected int leftSeconds = getLifeTime();

	private Object alivedSyncObj = new Object();

	public boolean isAlived() {
		synchronized (alivedSyncObj) {
			return isAlived;
		}

	}

	private Object knockingoutSyncObj = new Object();
	// 是否是被打倒的状态
	private boolean isKnockingout = false;

	public boolean isKnockingout() {
		synchronized (knockingoutSyncObj) {
			return isKnockingout;
		}
	}

	DrillShowCallback showCallback;
	DrillHideCallback hideCallback;
	KnockOutCallback knockOutCallback;

	private static float drillDuration = 1f;

	public Dwarf() {
		synchronized (alivedSyncObj) {
			isAlived = true;
		}
		synchronized (knockingoutSyncObj) {
			isKnockingout = false;
		}

		createPlatform();

		createDwart();
		dwarf.setVisible(false);
		dwarf.setPosition(getDwarfX(), 0);
		addChild(dwarf);
		hideCallback = new DrillHideCallback();
		showCallback = new DrillShowCallback();
		knockOutCallback = new KnockOutCallback();

		// blood
		blood = new BloodInDwarf(getLifeCount());
		if (getLifeCount() > 0) {
			blood.setPosition(getDwarfWidth() / 2.0f - getDwarfX(),
					-GameSystem.tex_man1.getHeight());
			blood.setVisible(false);
			this.addChild(blood);
		}

		String scoreText = "null";
		boolean isShowScore = true;
		if (getKnockoutScore() > 0) {
			scoreText = "+" + getKnockoutScore();
		} else if (getKnockoutScore() < 0) {
			scoreText = "" + getKnockoutScore();
		} else {
			isShowScore = false;
		}

		score = Label.make(scoreText, 25);
		score.setColor(WYColor3B.make(230, 10, 10));

		score.setVisible(false);
		if (isShowScore) {
			this.addChild(score, 3);
		}
	}

	private void createPlatform() {
		Texture2D tex = GameSystem.tex_platform;
		if (GameManager.instance.gameType == 1) {
			switch (GameManager.instance.getCurrentBgType()) {
			case spring:
				tex = GameSystem.tex_platform;
				break;
			case summer:
				tex = GameSystem.tex_platform_summer;
				break;
			case autumn:
				tex = GameSystem.tex_platform_autumn;
				break;
			case winter:
				tex = GameSystem.tex_platform_winter;
				break;
			case desert:
				tex = GameSystem.tex_platform_desert;
				break;
			case livingroom:
				tex = GameSystem.tex_platform_livingroom;
				break;
			case tarmac:
				tex = GameSystem.tex_platform_tarmac;
				break;
			}
		}
		platform = Sprite.make(tex);
		platform.setVisible(false);
		platform.setPosition(0, -(GameSystem.tex_man1.getHeight() / 2.0f)
				+ ResolutionIndependent.resolveDp(7.0f));
		this.addChild(platform);
	}

	/**
	 * 回收矮人
	 */
	public void recycleDwarf() {
		// 执行回收操作
		if (dwarf != null) {
			dwarf.autoRelease();
		}
		if (platform != null) {
			platform.autoRelease();
		}
		if (showTimer != null) {
			showTimer.autoRelease();
		}
		if (hideTimer != null) {
			hideTimer.autoRelease();
		}
		if (blood != null) {
			blood.autoRelease(true);
		}
		if (score != null) {
			score.autoRelease();
		}
	}

	/**
	 * 显示
	 */
	public void drillShow() {
		showTimer = ProgressTimer.make(dwarf);
		showTimer.autoRelease();
		showTimer.setStyle(ProgressTimer.VERTICAL_BAR_TB);
		showTimer.setVisible(false);
		addChild(showTimer);
		showTimer.runAction((Action) ProgressTo.make(drillDuration, 0, 100)
				.autoRelease());

		float x = getDwarfX();
		float startY = -GameSystem.tex_man1.getHeight();
		float endY = 0;
		IntervalAction move = (IntervalAction) MoveTo.make(drillDuration, x,
				startY, x, endY).autoRelease();
		move.setCallback(showCallback);
		showTimer.runAction(move);

		float bloodX = 0;
		float startYBlood = -GameSystem.tex_man1.getHeight() / 2.0f
				+ ResolutionIndependent.resolveDp(6);
		float endYBlood = GameSystem.tex_man1.getHeight() / 2.0f
				+ ResolutionIndependent.resolveDp(6);
		IntervalAction moveBlood = MoveTo.make(drillDuration, bloodX,
				startYBlood, bloodX, endYBlood);
		blood.runAction(moveBlood);

		// 启动生存时间倒计时
		liveTimer = new Timer();
		liveTimer.schedule(new TimerTask() {
			@Override
			public void run() {
				if (!GameManager.instance.isPaused) {
					leftSeconds--;
					if (leftSeconds <= 0) {
						Director.getInstance().runOnGLThread(new Runnable() {

							@Override
							public void run() {
								drillHide();
							}
						});

						if (liveTimer != null) {
							liveTimer.cancel();
							liveTimer = null;
						}
					}
				}
			}
		}, 1000, 1000);
	}

	/**
	 * 隐藏
	 */
	public synchronized void drillHide() {
		if (isHidingProgress) {
			return;
		}
		hideTimer = ProgressTimer.make(dwarf);
		hideTimer.autoRelease();
		hideTimer.setStyle(ProgressTimer.VERTICAL_BAR_TB);
		hideTimer.setVisible(false);
		addChild(hideTimer);
		hideTimer.runAction((Action) ProgressTo.make(drillDuration, 100, 0)
				.autoRelease());

		float x = getDwarfX();
		float startY = 0;
		float endY = -GameSystem.tex_man1.getHeight();
		IntervalAction move = (IntervalAction) MoveTo.make(drillDuration, x,
				startY, x, endY).autoRelease();
		move.setCallback(hideCallback);
		hideTimer.runAction(move);

		float bloodX = 0;
		float endYBlood = -GameSystem.tex_man1.getHeight() / 2.0f
				+ ResolutionIndependent.resolveDp(6);
		float startYBlood = GameSystem.tex_man1.getHeight() / 2.0f
				+ ResolutionIndependent.resolveDp(6);
		IntervalAction moveBlood = MoveTo.make(drillDuration, bloodX,
				startYBlood, bloodX, endYBlood);
		blood.runAction(moveBlood);

		isHidingProgress = true;
	}

	/**
	 * 打败
	 */
	public void knockOut() {
		if (!isAlived()) {
			return;
		}
		GameManager.instance.addKnockoutCount();
		// 加分
		GameManager.instance.addDwarfScore(getKnockoutScore());
		synchronized (knockingoutSyncObj) {
			isKnockingout = true;
		}
		if (liveTimer != null) {
			liveTimer.cancel();
			liveTimer = null;
		}
		IntervalAction blink = (IntervalAction) Blink.make(0.5f, 3)
				.autoRelease();
		blink.setCallback(knockOutCallback);
		dwarf.runAction(blink);

		IntervalAction scoreAction = (IntervalAction) FadeTo.make(0.5f, 255,
				100).autoRelease();
		score.runAction(scoreAction);
	}

	class KnockOutCallback implements Callback {

		@Override
		public void onStart(int arg0) {
			dwarf.setVisible(true);
			score.setVisible(true);
			if (hideTimer != null) {
				hideTimer.setVisible(false);
			}
			if (showTimer != null) {
				showTimer.setVisible(false);
			}
			blood.setVisible(false);
		}

		@Override
		public void onStop(int arg0) {
			dwarf.setVisible(false);
			score.setVisible(false);
			platform.setVisible(false);
			synchronized (alivedSyncObj) {
				isAlived = false;
			}
			finishDwarf();
			recycleDwarf();
		}

		@Override
		public void onUpdate(int arg0, float arg1) {

		}

	}

	class DrillShowCallback implements Callback {

		@Override
		public void onStart(int arg0) {
			dwarf.setVisible(false);
			showTimer.setVisible(true);
			blood.setVisible(true);
		}

		@Override
		public void onStop(int arg0) {
			dwarf.setVisible(true);
			showTimer.setVisible(false);
			platform.setVisible(true);
			doDwarfAction();
		}

		@Override
		public void onUpdate(int arg0, float arg1) {

		}
	}

	class DrillHideCallback implements Callback {

		@Override
		public void onStart(int arg0) {
			dwarf.setVisible(false);
			showTimer.setVisible(false);
			hideTimer.setVisible(true);
			platform.setVisible(false);
		}

		@Override
		public void onStop(int arg0) {
			hideTimer.setVisible(false);
			blood.setVisible(false);
			isHidingProgress = true;
			if (isAlived()) {
				synchronized (knockingoutSyncObj) {
					if (!isKnockingout) {
						drillhideOverProcess();
						synchronized (alivedSyncObj) {
							isAlived = false;
						}
						// 隐藏不算finish
						// finishDwarf();
						recycleDwarf();
					}
				}

			}

		}

		@Override
		public void onUpdate(int arg0, float arg1) {

		}
	}

	public WYRect getRect() {
		// TODO lc 需要重新计算打击位置,细化到子类中
		WYRect rect = WYRect.make(this.getPositionX() - (getDwarfWidth() / 2)
				* this.getScaleX(),
				this.getPositionY() - (GameSystem.tex_man1.getHeight() / 2)
						* this.getScaleY(), getDwarfWidth() * this.getScaleX(),
				GameSystem.tex_man1.getHeight() * this.getScaleY());
		return rect;
	}

	public boolean isHit(WYPoint point) {
		// TODO lc 需要重新计算打击位置,细化到子类中
		return this.getRect().containsPoint(point);
	}

	/**
	 * 处理矮人重新返回地洞
	 */
	protected void drillhideOverProcess() {
		if (isAlived())
		// 扣血
		{
			GameManager.instance.changeGameHeart(false);
			AudioHelper.lostHeart();
		}
	}

	protected void finishDwarf() {
		GameManager.instance.finishOneDwarf();
	}

	/**
	 * 创建矮人
	 * 
	 * @param index
	 */
	protected abstract void createDwart();

	/**
	 * 敲打矮人
	 * 
	 * @param power
	 * @return 1.打击成功 2.打击无效
	 */
	public abstract int knock(int power);

	/**
	 * 获取矮人的存活时间(秒)
	 */
	protected abstract int getLifeTime();

	/**
	 * 获取矮人的血量
	 * 
	 * @return
	 */
	protected abstract int getLifeCount();

	/**
	 * 获取dwarf的x位置
	 * 
	 * @return
	 */
	protected abstract float getDwarfX();

	/**
	 * 开始矮人的固定动画
	 */
	protected abstract void doDwarfAction();

	/**
	 * 获取每个矮人的宽度
	 */
	protected abstract float getDwarfWidth();

	/**
	 * 获取矮人被打倒的分数
	 * 
	 * @return
	 */
	protected abstract int getKnockoutScore();
}
